home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2002 #11
/
Amiga Plus CD - 2002 - No. 11.iso
/
Tools
/
Development
/
Feelin021015
/
Examples
/
Class3.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-10-28
|
8KB
|
273 lines
#include <stdio.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/feelin_protos.h>
#include <libraries/feelin.h>
struct FeelinBase *FeelinBase;
///OBJ
// This is the instance data for our custom class.
struct LocalObjectData {
WORD x,y, sx,sy;
};
//+
/// mAskMinMax
/*
Area.AskMinMax() will be called before the window is opened. We need to
tell Feelin the minimum and maximum size of our object.
When you are the first receiving the method the fields _minw() and
_minh() are set to zero and the fields _maxw() and _maxh() to FV_MAXMAX.
We can add values to _minw() and _minh() or set _maxw() and _maxh() if
we need to. Then we pass the method to our superclass.
When the method reaches Area class these values will be adjusted
according to FA_MinXxx, FA_FixedXxx and FA_FixXxx attributes.
*/
ULONG SAVEDS mAskMinMax(struct FeelinClass *psClass,APTR Obj,ULONG *pnArgs)
{
_minw(Obj) += 100; _minh(Obj) += 040;
_maxw(Obj) = 500; _maxh(Obj) = 300;
return F_SuperDoA(psClass,Obj,FM_AskMinMax,pnArgs);
}
//+
/// mDraw
/*
Draw method is called whenever Feelin feels (obviously ;-)) we should
render our object. This usually happens after layout is finished. Note:
You may only render within the rectangle _mleft(), _mtop(), _mwidth(),
_mheight().
*/
ULONG SAVEDS mDraw(struct FeelinClass *psClass,APTR Obj,struct LocalObjectData *psLOD,struct FS_Draw *psDraw)
{
APTR rp;
/*
Let our superclass draw itself first, Area class would e.g. draw the
frame and clear the whole region. What it does exactly depends on flags.
*/
F_SuperDoA(psClass,Obj,FM_Draw,(ULONG *)psDraw);
/*
IF FF_Draw_Object isn't set, we shouldn't draw anything. Feelin just
wanted to update the frame or something like that.
*/
rp = _rp(Obj);
if (psDraw->Flags & FF_Draw_Update) // called from our input method
{
if (psLOD->sx || psLOD->sy)
{
_BPen(_pen(Obj,FV_Pen_Shine));
ScrollRaster(rp,psLOD->sx,psLOD->sy,_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
_BPen(_pen(Obj,FV_Pen_Dark));
psLOD->sx = NULL;
psLOD->sy = NULL;
}
else
{
_APen(_pen(Obj,FV_Pen_Shadow));
_Plot(psLOD->x,psLOD->y);
}
}
else if (psDraw->Flags & FF_Draw_Object)
{
_APen(_pen(Obj,FV_Pen_Shine));
_Boxf(_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
}
return NULL;
}
//+
/// mActive
/*
Area class always creates an EventHandler structure in case of some
inputmodes. As we handle events instead of Area class we can use it as
we want. It will save us some allocations ;-)
Using F_ModifyHandler() to modify IDCMP flags it's a piece of cake to
request IDCMP events.
*/
ULONG SAVEDS mActive(struct FeelinClass *psClass,APTR Obj,BOOL bState)
{
if (bState)
{
F_Do(Obj,FM_ModifyHandler,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS,NULL);
}
else
{
F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS);
}
return F_SuperDoA(psClass,Obj,bState ? FM_Active : FM_Inactive,NULL);
}
//+
///mHandleEvent
/*
in mSetup() we said that we want get a message if mousebuttons or keys
pressed so we have to define the input-handler
Note :
This is really a good example, because it shows how to use critical
events carefully:
IDCMP_MOUSEMOVE is only needed when left-mousebutton is pressed, so we
dont request this until we get a SELECTDOWN-message and we reject
IDCMP_MOUSEMOVE immeditly after we get a SELECTUP-message
*/
ULONG SAVEDS mHandleEvent(APTR Obj, struct LocalObjectData *psLOD, struct FS_HandleEvent *psHE)
{
#define _between(a,x,b) ((x) >= (a) && (x) <= (b))
#define _isinobject(x,y) (_between(_mx(Obj),(x),_mx(Obj) + _mw(Obj) - 1) && _between(_my(Obj),(y),_my(Obj) + _mh(Obj) - 1))
/*
Note on Arrows handling :
If you don't handle arrows return NIL, this will allow Window object to
cycle through its chain using arrows instead of tabulations (more
confortable hu ?), else return your object. Currently, result is only check
against NIL, but this may change in future, so return your object.
*/
if (psHE->Key != FV_Key_None)
{
switch (psHE->Key)
{
case FV_Key_Left: psLOD->sx = -1; break;
case FV_Key_Right: psLOD->sx = 1; break;
case FV_Key_Up: psLOD->sy = -1; break;
case FV_Key_Down: psLOD->sy = 1; break;
default: return NULL;
}
F_Draw(Obj,FF_Draw_Update);
return ((ULONG)Obj); // Forbid arrow cycling, because *WE* handle key events.
}
else if (psHE->Msg->Class == IDCMP_MOUSEBUTTONS)
{
if (psHE->Msg->Code == SELECTDOWN)
{
if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
{
psLOD->x = psHE->Msg->MouseX;
psLOD->y = psHE->Msg->MouseY;
F_Draw(Obj,FF_Draw_Update);
// Only request IDCMP_MOUSEMOVE if we realy need it
F_Do(Obj,FM_ModifyHandler,IDCMP_MOUSEMOVE,NULL);
}
}
else
{
// Reject IDCMP_MOUSEMOVE because lmb is no longer pressed
F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_MOUSEMOVE);
}
}
else if (psHE->Msg->Class == IDCMP_MOUSEMOVE)
{
if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
{
psLOD->x = psHE->Msg->MouseX;
psLOD->y = psHE->Msg->MouseY;
F_Draw(Obj,FF_Draw_Update);
}
}
return NULL;
}
//+
///myDispatcher
ULONG ASM SAVEDS myDispatcher(REG_A2 struct FeelinClass *psClass,REG_A0 APTR Obj,REG_D0 ULONG nMethod,REG_A1 ULONG *pnArgs)
{
struct LocalObjectData *psLOD;
psLOD = INST_DATA(psClass,Obj);
/*
Here comes the dispatcher for our custom class. Unknown/unused methods are
passed to the superclass immediately.
*/
switch (nMethod)
{
case FM_AskMinMax: return mAskMinMax (psClass,Obj,pnArgs);
case FM_Draw: return mDraw (psClass,Obj,psLOD,(struct FS_Draw *)pnArgs);
case FM_HandleEvent: return mHandleEvent (Obj,psLOD,(struct FS_HandleEvent *)pnArgs);
case FM_Active: return mActive (psClass,Obj,TRUE);
case FM_Inactive: return mActive (psClass,Obj,FALSE);
default: return F_SuperDoA (psClass,Obj,nMethod,pnArgs);
}
}
//+
/// Main
void main()
{
APTR c,w,myobj;
struct FeelinClass *psFCC;
if (FeelinBase = (struct FeelinBase *)OpenLibrary("feelin.library",FV_VERSION))
{
/*
Create the new custom class with a call to F_CreateClass().
This function returns a feelinClass structure. You must use class.id to
create instance of your custom class. This ID is unique and made by
F_CreateClass() when ID is NIL.
*/
if (psFCC = F_CreateClass(FA_SuperID, FC_Area,
FA_DataSize, sizeof (struct LocalObjectData),
FA_Dispatcher, myDispatcher,
TAG_DONE))
{
c = ClientObject,
Child, w = WindowObject, FA_Window_Title, "A rather complex custom class",
Child, VGroup,
Child, TextObject, FA_FixedHeight,TRUE, DontChain, TextFrame, TextBack, FA_Text, "`c`iPaint `nwith `bmouse`n,\n`iScroll `nwith `bcursor keys`n.", End,
Child, myobj = F_NewObj(psFCC->ID, TextFrame, TAG_DONE),
End,
FA_Window_ActiveObject, myobj, // Safe here
End,
End;
if (c)
{
F_Do(w,FM_Notify,FA_Window_CloseRequest,TRUE, c,2,FM_Client_ReturnID,FV_Client_Quit);
F_Set(w,FA_Window_Open,TRUE);
F_DoA(c,FM_Client_Run,NULL);
F_DisposeObj(c);
}
F_RemoveClass(psFCC);
}
else
{
Printf("Could not create custom class.\n");
}
CloseLibrary((struct Library *)FeelinBase);
}
else
{
Printf("Failed to open feelin.library\n");
}
}
//+